package reflectdemo1;
import java.lang.reflect.*;
/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 74646
 * Date: 2022-03-30
 * Time: 14:01
 */
public class ReflectClassDemo {
    /**
     * 通过Class类的 newInstance 方法获取 Student 对象
     */
    public static void reflectNewInstance(){
        try {
            Class<?> c1 = Class.forName("reflectdemo1.Student"); //使用forName方法获取Class对象
            /**
             * 使用 newInstance()方法创建类的实例（(Student类)类外实例化对象）
             * 返回类型：T 。可以直接使用Object类型接收。如果使用Student类型接收，需要强制类型转换
             */
            //Object student =  c1.newInstance();
            Student student = (Student) c1.newInstance();
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) { //使用newInstance()方法，如果实例化失败就抛出该异常
            e.printStackTrace();
        } catch (IllegalAccessException e) { //使用newInstance()方法，如果创建实例的类是不可访问的，就抛出该异常
            e.printStackTrace();
        }
    }


    /**
     * 反射私有的构造方法
     */
    public static void reflectPrivateConstructor(){
        try {
            Class<?> c1 = Class.forName("reflectdemo1.Student"); //使用forName方法获取Class对象

            /**
             * getDeclaredConstructor方法：公开和私有的构造方法都可以获取到
             * 这里以获取私有的构造方法演示
             */
            Constructor<?> constructor =  c1.getDeclaredConstructor(String.class,int.class);

            /**
             * 利用反射访问 私有的 属性/方法 之前要先调用 setAccessible 方法，设置权限
             * 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查（将私有的属性设置为可访问）。
             * 值为 false 则指示反射的对象应该实施 Java 语言访问检查;
             * 如果获取的不是私有的方法或属性，可不用调用此方法
             */
            constructor.setAccessible(true);

            /**
             *  获取指定的构造方法，然后使用newInstance方法创建类的实例
             *   private Student(String name,int age) --> Student 类中私有的构造方法
             */
            Student student = (Student) constructor.newInstance("IDEA",20);

            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) { //如果没有找到匹配的构造方法，就会抛出该异常
            e.printStackTrace();
        } catch (InvocationTargetException e) { //如果获取的构造方法抛出了异常，就会抛出该异常
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 反射属性，获取私有或公开的
     */
    public static void reflectPrivateField(){
        try {
            Class<?> c1 = Class.forName("reflectdemo1.Student"); //使用forName方法获取Class对象

            Student student = (Student) c1.newInstance();

            /**
             *  获取私有的属性
             *  private String name --> Student 类中私有的属性
             */
            Field field = c1.getDeclaredField("name");
            field.setAccessible(true);
            //设置（修改）获取到的属性
            field.set(student,"张三");
            System.out.println(student);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) { //如果没有找到匹配的属性，就会抛出该异常
            e.printStackTrace();
        }
    }

    /**
     * 反射方法，获取私有或公开的
     */
    public static void reflectPrivateMethod(){
        try {
            Class<?> c1 = Class.forName("reflectdemo1.Student"); //使用forName方法获取Class对象

            Student student = (Student) c1.newInstance();

            //获取私有的方法
           Method method =  c1.getDeclaredMethod("func", String.class);
           method.setAccessible(true);

            /**
             * 调用私有的方法
             * private void func(String str) --> Student 类中私有的方法
             */
           method.invoke(student,"我是私有方法的参数");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) { //如果没有找到匹配的方法，就会抛出该异常
            e.printStackTrace();
        } catch (InvocationTargetException e) { //如果获取的方法抛出了异常，就会抛出该异常
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        reflectPrivateMethod();
    }
}



